\chapter{GNU Regex 语法变量}\label{gnu-app-syntax-macros}

正则表达式用一个字符串来表达\enquote{具备某种规则}的字符串集合，该字符串便称
为\enquote{正则表达式}。正则表达式中的字符主要可分为两大类：

\begin{itemize}
  \item 普通字符，代表的是字面含义
  \item 运算符，代表的是某种特殊的规则
\end{itemize}

其中，运算符的含义可以在程序中根据需要进行设置。

\section{语法变量}

为使用GNU Regex版的用户界面，需要在\cinline{#include <regex.h>}引入GNU Regex%
之前，使用\cinline{#define _GNU_SOURCE}定义\cinline{_GNU_SOURCE}宏。

在GNU Regex用户界面中，可以通过\enquote{\cinline{re_syntax_options}}全局变量
设置正则表达式中运算符的处理方式，该变量称为\enquote{语法变量}。可以通过该
语法变量的各个位(统称为\enquote{语法位})表示运算符的开关(on/off)状态，
这些语法位可以通过GNU Regex定义的宏常量及这些常量的组合(\enquote{\cinline!|!}%
按位或运算)进行设置。

\section{语法常量}
以下是GNU Regex库中，可用于控制运算符功能及语法的宏常量：

\begin{description}
  \item[\cinline{RE_BACKSLASH_ESCAPE_IN_LISTS}:]如设置为on，则\verb|'\'|%
    在\cinline{[...]}或\cinline{[^...]}列表中表示转义运算符(如果是特殊字符，
    将其转义为普通字符)，否则为普通字符。例如，当设置为on时，\cinline{"[\.]"}
    表示\cinline{"[.]"}，而设置为off时，\cinline{"[\.]"}表示的是\cinline{"[\.]"}本身。
  \item[\cinline{RE_BK_PLUS_QM}:]如设置为on，则用\cinline{'\+'}表示其前面的字符重复
    1次及1次以上，用\cinline{'\?'}表示前面的字符出现0次或1次，否则则分别用\cinline{'+'}
    和\cinline{'?'}表示对应操作。如果\cinline{RE_LIMITED_OPS}设置为on，则该设置无效。
  \item[\cinline{RE_CHAR_CLASSES}:]如设置为on，才可以在列表中使用字符类(char classes)，
    否则则不能。
  \item[\cinline{RE_CONTEXT_INDEP_ANCHORS}:]如设置为on，则\cinline{'^'}和\cinline{'$'}
    在任何列表之外都表示运算符，否则仅在特定上下文中表示运算符。
  \item[\cinline{RE_CONTEXT_INDEP_OPS}:]如设置为on，则在列表之外的任何地方都是
    运算符，如果设置为off，则仅在特定上下文中表示运算符，在其它情况下表示普通字符。具体来讲，
    如果未设置该位，则\cinline{'*'}和\cinline{'+'}(如\cinline{RE_LIMITED_OPS}设置为off)及
    \cinline{'?'}(或\cinline{'\+'}和\cinline{'\?'}，取决于\cinline{RE_BK_PLUS_QM})
    仅在不是正则表达式的第1个字符或仅位于组开始\cinline{'('}或辅助运算符\cinline{'|'}%
    之后时才表示是重复运算符。同样，如果\verb|'{'|%
    (或\verb|'\{'|，取决于\cinline{RE_NO_BK_BRACES}的设置)是一个有效区间的开始，
    并且设置了\cinline{RE_INTERVALS}，那么它们也是如此。
  \item[\cinline{RE_CONTEXT_INVALID_DUP}:]如设置为on，表示区段的\verb|'{'|不能
    出现在正则表达式的开始，或紧跟一个辅助运算符\cinline{'|'}、分组开始运算符%
    \verb|'('|或区段结束运算符\verb|'}'|之后。
  \item[\cinline{RE_CONTEXT_INVALID_OPS}:]如设置为on，则重复运算符
      (\cinline{*}、\cinline{+}、\cinline{.}和\cinline{'?'})不可以
      位于正则表达式的特定位置。具体来讲，如果出现如下情况，则正则表达式无效：
      \begin{itemize}
        \item 重复运行符出现在正则表达式的开始或仅跟随于行开始运算符\verb|'^'|%
          或组开始运算符\verb|'('|或辅助运算符之后
        \item 运算符\verb|'?'|位于正则表达式的开始或末尾，并且在行结束运算符%
          \verb|'$'|之前或紧跟在一个辅助运算符或组开始运算符之后
      \end{itemize}
      如设置为off，则可以将重复运算符和辅助运算符置于正则表达式中任意位置。
      至于是否会被用作运算符，则取决于其它语法位的设置。
  \item[\cinline{RE_DEBUG}:]如设置为on，并且使用\cinline{-DDEBUG}编译GNU Regex%
      库时，会打开内部调试功能，如设置为off,则会关闭调试功能。
  \item[\cinline{RE_DOT_NEWLINE}:]如设置为on，表示任意字符的运算符\cinline{.}%
      可以匹配newline，如果设置为off，则不做匹配。
  \item[\cinline{RE_DOT_NOT_NULL}:]如果设置为on，表示任意字符的运算符\cinline{.}%
      不匹配null字符，如果设置为off，则可以匹配。
  \item[\cinline{RE_HAT_LISTS_NOT_NEWLINE}:]如果设置为on，则\cinline{[^...]}%
      不匹配列表将不匹配newline，如果设置为off，则可以匹配。
  \item[\cinline{RE_ICASE}:]如果设置为on，则在匹配时，会忽略大小写，否则，则区分
      大小写。
  \item[\cinline{RE_INTERVALS}:]如设置为on，表示可以使用区间运算符，如用%
      \cinline{"fo{4}"}指定重复次数或用\cinline{"fo{2,4}"}指定重复区间，否则，
      则不能使用区间运算符。
  \item[\cinline{RE_INVALID_INTERVAL_ORD}:]如设置为on，则在语法上无效的区间
      运算符被当作普通字符，例如，扩展正则表达式\cinline|"a{1"|将被视为%
      \cinline|"a\{1"|。
  \item[\cinline{RE_LIMITED_OPS}:]如设置为on，则不可以使用\cinline{'+'}(匹配1次或多次)、%
      \cinline{'*'}(匹配0次或多次)或\cinline{'|'}运算符，如果设置为off，则可以使用。
  \item[\cinline{RE_NEWLINE_ALT}:]如设置为on，则newline表示可选运算符%
      \cinline{'?'}，如果设置为off，则newline为普通字符。
  \item[\cinline{RE_NO_BK_BRACES}:]如设置为on，则\cinline|'{'|和\cinline|'}'|%
      分别表示区间开始和结束运算符，否则则分别使用\cinline|'\{'|和\cinline|'\}'|%
      表示区间开始和结束运算符。
  \item[\cinline{RE_NO_BK_PARENS}:]如设置为on，则\cinline|'('|和\cinline|')'|%
      分别表示分组开始和结束运算符，否则则分别使用\cinline|'\('|和\cinline|'\)'|%
      表示分组开始和结束运算符。
  \item[\cinline{RE_NO_BK_REFS}:]如设置为on，则不能使用\cinline{"\数字"}引用
      前面用分组设置的已匹配字符，如果设置为off，则可以使用。
  \item[\cinline{RE_NO_BK_VBAR}:]如设置为on，则使用\cinline{'|'}表示辅助运算符%
      (\enquote{可以有，也可以没有})，否则则使用\cinline{"\|"}。
      如果设置了\cinline{RE_LIMITED_OPS}，则该设置无效。
  \item[\cinline{RE_NO_EMPTY_RANGES}:]如果设置为on，则使用指定范围运算符时，
      其结束值不能低于起始值，否则则无效。如果设置了off，则认为这样的设置为空。
  \item[\cinline{RE_NO_GNU_OPS}:]如果设置为on，则无法识别GNU Regex运算符，
      如果设置为off，则可以识别。
  \item[\cinline{RE_NO_POSIX_BACKTRACKING}:]如果设置为on，一旦完成整个正则表达式
      的匹配，则表示匹配成功，不做回溯。这意味着可能不是\enquote{最左匹配}。
  \item[\cinline{RE_NO_SUB}:]如果设置为on，则在执行\cinline{re_compile_pattern}时，
      会将\cinline{no_sub}设置为1。这会使得匹配和搜索API无法记录子字符串的匹配信息。
  \item[\cinline{RE_UNMATCHED_RIGHT_PAREN_ORD}:]如设置为on并且正则表达式中没有
      组开始运算符，那么Regex会将原本属于组结束运算符的内容(根据%
      \cinline{RE_NO_BK_PARENS}的设置)视为\cinline{')'}。
\end{description}

\section{语法变量预设值}

如果使用GNU Regex编程，则可以使用任意语法位的组合或GNU Regex预设的组合对正则
表达式的编译结果(又称为模式缓冲区)的语法进行设置。除了POSIX基础和扩展正则表
达式的语法外，这些配置还定义了GNU Emacs、POSIX Awk、传统Awk、Grep和Egrep程序
的语法。

这些预设值在\texttt{regex.h}中进行定义：

\cvfile[label=code-syntax-predefined]{GNU Regex语法预设值}
  {gnu-regex/codes/regex-head/regex-syntax-predefined.h}

\section{对照元素和字符}

POSIX将字符的概念概括为对照元素，它将对照元素定义为\enquote{当前对照序列中
定义为对照单位的一个或多个字节序列}。

这从两个方面概括了字符的概念。首先，一个字符可以映射到2个或更多的对照元素中。
例如，德文的\enquote{ß}可以对照为一个对照元素\enquote{s}后再跟一个\enquote{s}。
其次，两个或多个字符可以映射到一个对照元素。例如，捷克语中的\enquote{ch}可以
对照到\enquote{h}之后并在\enquote{i}之前。

由于POSIX的\enquote{对照元素}保留了\enquote{字符}的基本概念，因此在本文档中
使用字符，也就读者更为熟悉的术语。

\section{`\textbackslash' 运算符}

\verb|'\'|字符有4种不同的含义，这取决于使用该字符的上下文及语法位的设置。
它可以是：

\begin{description}
  \item[字符原义:]如未设置\cinline{RE_BACKSLASH_ESCAPE_IN_LISTS}，则在
    \cinline{"[\]"}中表示\verb|'\'|本身。
  \item[转义字符:]如果是特殊字符，则将其转义为普通字符。例如\verb|'\.'|表示%
    \verb|'.'|字符，也就是说\verb|'.'|不再表示匹配任意字符。
    在此，要求设置\cinline{RE_BACKSLASH_ESCAPE_IN_LISTS}后在列表内
    使用\verb|'\'|或在列表外使用\verb|'\'|。
  \item[GNU运算符组合:]如果设置了\cinline{RE_BK_PLUS_QM}、 %
    \cinline{RE_NO_BK_BRACES}、 \cinline{RE_NO_BK_VAR}、 \cinline{RE_NO_BK_PARENS}%
    或\cinline{RE_NO_BK_REF}， 则\verb|'\'|与特定的普通字符的组合表示GNU Regex%
    运行符，如：
      \begin{itemize}
        \item \cinline|'\b'| 表示单词边界，例如\cinline{"\bhere\b"}在%
          \cinline{"there and here"}中可以找到\cinline{"here"}
          这个完整单词，而不是单词\cinline{"there"}中的\cinline{"here"}部分。
        \item \cinline|'\B'| 表示单词内部，例如%
          \cinline{"\Bhere"}在\cinline{"there and here"}中可以找到%
          \cinline{"there"}单词中的\cinline{"here"}部分，而不是完整的单词\cinline{"here"}。
        \item \cinline|'\<'| 表示单词开始，例如%
          \cinline{"\<here"}在\cinline{"there and here"}中可以找到%
          \cinline{"here"}这个完整单词，而不是单词\cinline{"there"}中的\cinline{"here"}部分。
        \item \cinline|'\>'| 表示单词结束，例如%
          \cinline{"here\>"}在\cinline{"there and here"}中可以先找到%
          \cinline{"there"}单词中的\cinline{"here"}部分。
        \item \cinline|'\w'| 表示可以组成单词的字符，例如%
          \cinline{"\where"}在\cinline{"?here and there"}中可以找到单词%
          \cinline{"there"}。
        \item \cinline|'\W'| 表示非字母，例如%
          \cinline{"\Where"}在\cinline{"?here and there"}中可以找到%
          \cinline{"?here"}。
        \item \cinline|"\sclass"|] 与\cinline{[[:space:]]}列表等价
        \item \cinline|"\Sclass"|] 与\cinline{[^[:space:]]}列表等价
        \item \cinline|'\`'| 表示开始，例如%
          \cinline{"\`there"}在\cinline{"there and here"}和%
          \cinline{"here and there"} 中会找到 \cinline{"there and here"}%
          这个字符串开始的单词\cinline{"there"}。
        \item \cinline|'\''| 表示结束，例如%
          \cinline{"there\'"}在\cinline{"there and here"}和%
          \cinline{"here and there"} 中可以找到\cinline{"here and there"}%
          这个字符串结束的单词\cinline{"there"}。
      \end{itemize}
  \item[不代表任何字符:]在其它情况下\verb|'\'|是可以被忽略的，例如\verb|\n|%
      能够匹配表示\verb|'n'|。
\end{description}

\section{正则表达式运算符}

正则表达式主要是使用普通字符结合运算符实现的，在GNU Regex库中，正则表达式的运算
符可以分为三类：

\subsection{通用运算符}

这一类运算符主要用于符合POSIX标准的正则表达式中，但在GNU Regex库中也可以使用，
它们主要有两种形式：

单一符号或加上\verb|'\'|的单一符号。其中，不同语法位设置了\verb|'\'|符号的使用
方法。这些运算符有：
\begin{description}
  \item[本身字符:]除运算符外的字符，如\cinline{"here"}就表示%
    \cinline{"here"}本身。
  \item[任意字符:] \cinline{'.'}，如\cinline{"foo."}表示\cinline{"foo"}%
    再加上任意一个字符的意思(\cinline{"foox"}等)。
  \item[重复字符:] \cinline{'*'}，如\cinline{"foo*"}表示\cinline{"foo"}或%
    \cinline{"fooo"}或\cinline{"foooo"}$\ldots$所构成的集合。
  \item[重复至少1次:] \cinline{'+'}，如\cinline{"foo+"}表示\cinline{"fooo"}或%
    \cinline{"foooo"}$\ldots$所构成的集合。
  \item[重复至少0次或1次:] \cinline{'?'}，如\cinline{"foo?"}表示\cinline{"foo"}或%
    \cinline{"fooo"}所构成的集合。
  \item[重复区间:] \cinline|{count}|或\cinline|{min,}|或\cinline|{min,max}|，
      如\cinline{"foo{2}"}表示\cinline{"foooo"}所构成的集合。
  \item[或:] \cinline{'|'}，如\cinline{"foo|FOO"}表示\cinline{"foo"}或%
      \cinline{"FOO"}所构成的集合。
  \item[列表:] \cinline{"[...]"}或\cinline{"[^...]"}，如\cinline{"[fo]"}%
      表示\cinline{'f'}或\cinline{'o'}所构成的集合。而\cinline{"[^fo]"}%
      表示非\cinline{'f'}且非\cinline{'o'}所构成的集合。
  \item[类别:] \cinline{"[:...:]"}，例如：
  \begin{itemize}
    \item \cinline{"[:alnum:]:"} 表示英文字母或阿拉伯数字，也就是\cinline{a-z}、
      \cinline{A-Z}和\cinline{0-9}。
    \item \cinline{"[:alpha:]:"} 表示英文字母，也就是\cinline{a-z}、\cinline{A-Z}。
    \item \cinline{"[:blank:]:"} 表示空白(空格或tab)
    \item \cinline{"[:cntrl:]:"} 表示控制字符，其ASCII码值介于040到0177之间
    \item \cinline{"[:digit:]:"} 表示阿拉伯数字，也就是\cinline{0-9}
    \item \cinline{"[:graph:]:"} 表示除了空格以，可打印字符
    \item \cinline{"[:lower:]:"} 表示小字英文字母，也就是\cinline{a-z}
    \item \cinline{"[:print:]:"} 表示可打印字符
    \item \cinline{"[:punct:]:"} 表示除\cinline{"[:cntrl:]"}和\cinline{"[:alnum:]"}之外的字符
    \item \cinline{"[:space:]:"} 表示空白，包括空格、换行、垂直跳行和换页符
    \item \cinline{"[:upper:]:"} 表示大写字母，也就是\cinline{A-Z}
    \item \cinline{"[:xdigit:]:"} 表示十六进制数字，也就是\cinline{0-9}、%
      \cinline{a-f}、\cinline{A-F}
  \end{itemize}
  \item[指定范围:] \cinline{'-'}，例如\cinline{"[2-4]"}表示\cinline{'2'}、%
      \cinline{'3'}、\cinline{'4'}
  \item[群组:] \cinline{"(...)"}，例如\cinline{"(ab)+"}表示\cinline{"ab"}、%
       \cinline{"abab"}、\cinline{"ababab"}$\ldots$
  \item[引用群组:] \cinline{"\数字"}，例如\cinline{"(a)b\1c\1"}表示
      \cinline{"abaca"}
  \item[行首:] \cinline{'^'}，例如\cinline{"^foo"}表示\cinline{"foo"}必需
      出现在行首
  \item[行尾:] \cinline{'$'}，例如\cinline{"foo$"}表示\cinline{"foo"}必需
      出现在行尾
\end{description}
